#include "customdata.h"
#include <QtMath>
#include <QDebug>

CustomData::CustomData()
{
    splineProxy = new SplineProxy();
}

void CustomData::AddStringData(QList<QList<float>> lstX,QList<QList<float>> lstY,QList<QList<float>> lstZ)
{
    lstStringX = lstX;
    lstStringY = lstY;
    lstStringZ = lstZ;

    xStringMin = xStringMax = lstStringX[0].at(0);
    yStringMin = yStringMax = lstStringY[0].at(0);
    zStringMin = zStringMax = lstStringZ[0].at(0);

    for(int i=0; i< lstStringX.count();i++)
    {
        for(int j=0;j<lstStringX[0].count();j++)
        {
            xStringMin = xStringMin > lstStringX[i].at(j) ? lstStringX[i].at(j) : xStringMin;
            xStringMax = xStringMax < lstStringX[i].at(j) ? lstStringX[i].at(j) :xStringMax;

            yStringMin = yStringMin > lstStringY[i].at(j) ? lstStringY[i].at(j) : yStringMin;
            yStringMax = yStringMax < lstStringY[i].at(j) ? lstStringY[i].at(j): yStringMax;

            zStringMin = zStringMin > lstStringZ[i].at(j) ? lstStringZ[i].at(j) : zStringMin;
            zStringMax = zStringMax < lstStringZ[i].at(j) ? lstStringZ[i].at(j) : zStringMax;
        }
    }
}

void CustomData::AddWellData(QList<QList<float>> lstX,QList<QList<float>> lstY,QList<QList<float>> lstZ)
{
    lstWellX = lstX;
    lstWellY = lstY;
    lstWellZ = lstZ;

    xWellMin = xWellMax = lstWellX[0].at(0);
    yWellMin = yWellMax = lstWellY[0].at(0);
    zWellMin = zWellMax = lstWellZ[0].at(0);

    for(int i=0; i< lstWellX.count();i++)
    {
        for(int j=0;j<lstWellX[0].count();j++)
        {
            xWellMin = xWellMin > lstWellX[i].at(j) ? lstWellX[i].at(j) : xWellMin;
            xWellMax = xWellMax < lstWellX[i].at(j) ? lstWellX[i].at(j) :xWellMax;

            yWellMin = yWellMin > lstWellY[i].at(j) ? lstWellY[i].at(j) : yWellMin;
            yWellMax = yWellMax < lstWellY[i].at(j) ? lstWellY[i].at(j): yWellMax;

            zWellMin = zWellMin > lstWellZ[i].at(j) ? lstWellZ[i].at(j) : zWellMin;
            zWellMax = zWellMax < lstWellZ[i].at(j) ? lstWellZ[i].at(j) : zWellMax;
        }
    }


}

void  CustomData::AddStringFEMData(QHash<QString,QVector<double>> data)
{
    stringFEMData = data;
//    QList<QString> lstName = data.keys();
//    QList<QVector<double>> lstData = data.values();
//    QList<int> lstIndex;
//    for(int i=0;i<lstName.count();i++)
//    {
//      QStringList  lstTemp = lstName.at(i).split('_');
//      int index = lstTemp.at(lstTemp.count()-1).toInt();
//      lstIndex.append(index);
//    }

//    QString vxInterpName = lstName.at(lstIndex.indexOf(0));
//    QVector<double> vxBase = lstData.at(lstIndex.indexOf(0));

//    lstName.removeAt(lstIndex.indexOf(0));
//    lstData.removeAt(lstIndex.indexOf(0));

//    QVector<QVector<double>> vyBase = lstData.toVector();

//    QVector<double> vxInterp;
//    for(int i=0;i<lstStringZ.count();i++)
//    {
//        for(int j=0;j<lstStringZ.at(0).count();j++)
//        {
//            if(!vxInterp.contains(lstStringZ.at(i).at(j)))
//            {
//                vxInterp.append(lstStringZ.at(i).at(j));
//            }
//        }
//    }

//    QVector<QVector<double>> vyInterp = splineProxy->Interpol(vxBase,vyBase,vxInterp);

//    stringFEMData.insert(vxInterpName,vxInterp);
//    for(int i=0;i<lstName.count();i++)
//    {
//        stringFEMData.insert(lstName[i],vyInterp.at(i));
//    }
}
void  CustomData::AddTouchData(QHash<QString,QVector<double>> data)
{
    touchData = data;
}

QList<QString> CustomData::GetFEMParams()
{
    return stringFEMData.keys();
}

void CustomData::GetWellRange(float& xMin,float& xMax,float& yMin,float& yMax,float& zMin,float& zMax)
{
    xMin = xWellMin;
    xMax = xWellMax;
    yMin = yWellMin;
    yMax = yWellMax;
    zMin = zWellMin;
    zMax = zWellMax;
}

void CustomData::GetStringRange(float& xMin,float& xMax,float& yMin,float& yMax,float& zMin,float& zMax)
{
    xMin = xStringMin;
    xMax = xStringMax;
    yMin = yStringMin;
    yMax = yStringMax;
    zMin = zStringMin;
    zMax = zStringMax;
}

void CustomData::GetAxisInfo(float& xMin,float& xMax,float& yMin,float& yMax,float& zMin,float& zMax)
{
    xMin =   -xWellRate < -xStringRate ? -xWellRate : -xStringRate;
    xMax = xWellRate > xStringRate ? xWellRate :  xStringRate;

    yMin = -yWellRate  < -yStringRate ? -yWellRate : -yStringRate;
    yMax = yWellRate  > yStringRate ? yWellRate : yStringRate;

    zMin = -zWellRate < - zStringRate ? -zWellRate : -zStringRate;
    zMax = zWellRate > zStringRate ? zWellRate : zStringRate;
}

bool CustomData::IsExistStringData()
{
    if(lstStringX.count() != 0 && lstStringX.count() == lstStringY.count() && lstStringX.count() == lstStringZ.count())
        return true;
    return false;
}

bool CustomData::IsExistWellData()
{
    if(lstWellX.count() != 0 && lstWellX.count() == lstWellY.count() && lstWellX.count() == lstWellZ.count())
        return true;
    return false;
}

uint CustomData::GetStringVertexCount()
{
    if(IsExistStringData())
    {
        return stringVertorNum;
    }

    return 0;
}

uint CustomData::GetStringFaceCount()
{
    if(IsExistStringData())
    {
        return stringIndiceCount;
    }

    return 0;
}

uint CustomData::GetWellVertexCount()
{
    if(IsExistWellData())
    {
        return wellVertorNum;
    }

    return 0;
}

uint CustomData::GetWellFaceCount()
{
    if(IsExistWellData())
    {
        return wellIndiceCount;
    }

    return 0;
}

VertexData CustomData::GetStringVertexData(bool isDependOther,QList<float>* lstRange,ColorMap mapColor)
{
    //qDebug()<<mapColor.minColor << "," <<mapColor.maxColor;
    if(isDependOther)
    {
        xSetMin = lstRange->at(0);
        xSetMax = lstRange->at(1);
        ySetMin = lstRange->at(2);
        ySetMax = lstRange->at(3);
        zSetMin = lstRange->at(4);
        zSetMax = lstRange->at(5);
    }

    CalculateVertexDataAndFaceStripData(true,isDependOther,mapColor);

    return stringVertexData;

}

VertexData CustomData::GetWellVertexData(bool isDependOther,QList<float>* lstRange,ColorMap mapColor)
{
    if(isDependOther)
    {
        xSetMin = lstRange->at(0);
        xSetMax = lstRange->at(1);
        ySetMin = lstRange->at(2);
        ySetMax = lstRange->at(3);
        zSetMin = lstRange->at(4);
        zSetMax = lstRange->at(5);
    }

    CalculateVertexDataAndFaceStripData(false,isDependOther,mapColor);

    return wellVertexData;
}

QVector<QVector3D> CustomData::GetColorMapsByZ(bool isString,ColorMap colorMap)
{
    float stepZ = 0;
    if(isString)
    {
        stepZ = (zStringMax - zStringMin)/colorMap.mapLevels;
    }
    else
    {
        stepZ = (zWellMax - zWellMin)/colorMap.mapLevels;
    }

    //qDebug()<<"step z:"<<stepZ<<"min:"<<zWellMin<<"max:"<<zWellMax;
    float redStart = colorMap.minColor.redF();
    float blueStart = colorMap.minColor.blueF();
    float greenStart = colorMap.minColor.greenF();

    float redStop = colorMap.maxColor.redF();
    //redStop = redStop < redStart ? redStop + 1.0 : redStop;
    float blueStop = colorMap.maxColor.blueF();
    //blueStop = blueStop < blueStart ? blueStop + 1.0 : blueStop;
    float greenStop = colorMap.maxColor.greenF();
    //greenStop = greenStop < greenStart ? greenStop + 1.0 : greenStop;

    float redStep = (redStop - redStart) / colorMap.mapLevels;
    float greenStep = (greenStop - greenStart) / colorMap.mapLevels;
    float blueStep = (blueStop - blueStart) / colorMap.mapLevels;

    QVector<QVector3D> vectorColor;
    if(isString)
    {
        for(int i=0;i<lstStringZ.count();i++)
        {
            for(int j=0;j<lstStringZ.at(0).count();j++)
            {
                for(uint k=0;k<colorMap.mapLevels;k++)
                {
                    if(lstStringZ.at(i).at(j) >= (zStringMin + stepZ * k) && lstStringZ.at(i).at(j) < (zStringMin + stepZ * ( k + 1)))
                    {
                        float redCur = redStart + k * redStep;
                        //redCur = redCur > 1.0 ? redCur - 1.0 : redCur;
                        float greenCur = greenStart + k * greenStep;
                        //greenCur = greenCur > 1.0 ? greenCur - 1.0 : greenCur;
                        float blueCur = greenStart + k * blueStep;
                        //blueCur = blueCur > 255 ? blueCur - 255 : blueCur;
                        vectorColor.append(QVector3D(redCur,greenCur,blueCur));
                        //qDebug()<<i<<","<<j;
                        break;
                    }

                    if(lstStringZ.at(i).at(j) >= (zStringMin + stepZ * colorMap.mapLevels))
                    {
                        vectorColor.append(QVector3D(redStop,greenStop,blueStop));
                        //qDebug()<<i<<","<<j;
                        break;
                    }
                    //vectorColor.append(QVector3D(colorMap.maxColor.redF(),colorMap.maxColor.greenF(),colorMap.maxColor.blueF()));
                }
            }
        }
    }
    else
    {
        for(int i=0;i<lstWellZ.count();i++)
        {
            for(int j=0;j<lstWellZ.at(0).count();j++)
            {
                for(uint k=0;k<colorMap.mapLevels;k++)
                {
                    if(lstWellZ.at(i).at(j) >= (zWellMin + stepZ * k) && lstWellZ.at(i).at(j) < (zWellMin + stepZ * ( k + 1)))
                    {
                        float redCur = redStart + k * redStep;
                        //redCur = redCur > 1.0 ? redCur - 1.0 : redCur;
                        float greenCur = greenStart + k * greenStep;
                        //greenCur = greenCur > 1.0 ? greenCur - 1.0 : greenCur;
                        float blueCur = greenStart + k * blueStep;
                        //blueCur = blueCur > 255 ? blueCur - 255 : blueCur;
                        vectorColor.append(QVector3D(redCur,greenCur,blueCur));
                        //qDebug()<<i<<","<<j;
                        break;
                    }

                    if(lstWellZ.at(i).at(j) >= (zWellMin + stepZ * colorMap.mapLevels))
                    {
                        vectorColor.append(QVector3D(redStop,greenStop,blueStop));
                        //qDebug()<<i<<","<<j;
                        break;
                    }
                    //vectorColor.append(QVector3D(colorMap.maxColor.redF(),colorMap.maxColor.greenF(),colorMap.maxColor.blueF()));
                }
            }
        }
    }
    //qDebug()<<"Act : " <<vectorColor.count()<<"row: "<<lstWellZ.length() <<"col:"<< lstWellZ.at(0).count();
    return vectorColor;
}

QVector<QVector3D> CustomData::GetColorMapByName(QString name,ColorMap colorMap)
{
    //qDebug()<<"Name:"<<name<<",Min color:"<<colorMap.minColor<<",Max color:"<<colorMap.maxColor;

    QStringList arrName = name.split("_");
    if(arrName.last().toInt() == 0)
    {
        return GetColorMapsByZ(true,colorMap);
    }

    QList<QString> lstName = stringFEMData.keys();
    QList<int> lstIndex;
    for(int i=0;i<lstName.count();i++)
    {
      QStringList  lstTemp = lstName.at(i).split('_');
      int index = lstTemp.at(lstTemp.count()-1).toInt();
      lstIndex.append(index);
    }

        QString vxInterpName = lstName.at(lstIndex.indexOf(0));
        QVector<double> vxBase = stringFEMData.value(vxInterpName);

        QVector<double> vyBase = stringFEMData.value(name);

        QVector<double> vxInterp;
        for(int i=0;i<lstStringZ.count();i++)
        {
            for(int j=0;j<lstStringZ.at(0).count();j++)
            {
                if(!vxInterp.contains(lstStringZ.at(i).at(j)))
                {
                    vxInterp.append(lstStringZ.at(i).at(j));
                }
            }
        }

        QVector<double> vyInterp = splineProxy->Interpol(vxBase,vyBase,vxInterp);

    //    stringFEMData.insert(vxInterpName,vxInterp);
    //    for(int i=0;i<lstName.count();i++)
    //    {
    //        stringFEMData.insert(lstName[i],vyInterp.at(i));
    //    }

    QVector<QVector3D> vectorColor;
    QVector<double> vecZData = vxInterp;//stringFEMData.value(lstName.at(lstIndex.indexOf(0)));
    QVector<double> vecData = vyInterp;//stringFEMData.value(name);
    if(vecData.length() == 0)
        return vectorColor;

    double minValue = vecData.first();
    double maxValue = vecData.first();

    QVector<double>::Iterator iter;
    for(iter = vecData.begin();iter != vecData.end();iter++)
    {
        if(minValue > *iter)
        {
            minValue = *iter;
        }

        if(maxValue < *iter)
        {
            maxValue = *iter;
        }
    }

    float stepZ = 0;
    stepZ = (maxValue - minValue)/colorMap.mapLevels;

    //qDebug()<<"step z:"<<stepZ<<"min:"<<zWellMin<<"max:"<<zWellMax;
    float redStart = colorMap.minColor.redF();
    float blueStart = colorMap.minColor.blueF();
    float greenStart = colorMap.minColor.greenF();

    float redStop = colorMap.maxColor.redF();
    //redStop = redStop < redStart ? redStop + 1.0 : redStop;
    float blueStop = colorMap.maxColor.blueF();
    //blueStop = blueStop < blueStart ? blueStop + 1.0 : blueStop;
    float greenStop = colorMap.maxColor.greenF();
    //greenStop = greenStop < greenStart ? greenStop + 1.0 : greenStop;

    float redStep = (redStop - redStart) / colorMap.mapLevels;
    float greenStep = (greenStop - greenStart) / colorMap.mapLevels;
    float blueStep = (blueStop - blueStart) / colorMap.mapLevels;



    for(int i=0;i<lstStringZ.count();i++)
    {
        for(int j=0;j<lstStringZ.at(0).count();j++)
        {
            int index = vecZData.indexOf(lstStringZ.at(i).at(j));
            double curData = vecData.at(index);
            for(uint k=0;k<colorMap.mapLevels;k++)
            {
                if(curData >= (minValue + stepZ * k) && curData < (minValue + stepZ * ( k + 1)))
                {
                    float redCur = redStart + k * redStep;
                    //redCur = redCur > 1.0 ? redCur - 1.0 : redCur;
                    float greenCur = greenStart + k * greenStep;
                    //greenCur = greenCur > 1.0 ? greenCur - 1.0 : greenCur;
                    float blueCur = greenStart + k * blueStep;
                    //blueCur = blueCur > 255 ? blueCur - 255 : blueCur;
                    vectorColor.append(QVector3D(redCur,greenCur,blueCur));
                    //qDebug()<<i<<","<<j;
                    break;
                }

                if(curData >= (minValue + stepZ * colorMap.mapLevels))
                {
                    vectorColor.append(QVector3D(redStop,greenStop,blueStop));
                    //qDebug()<<i<<","<<j;
                    break;
                }
                //vectorColor.append(QVector3D(colorMap.maxColor.redF(),colorMap.maxColor.greenF(),colorMap.maxColor.blueF()));
            }
        }
    }

    return vectorColor;
}

QVector<uint> CustomData::GetStringFaceStripData()
{
    return stringFaceStrip;
}

QVector<uint> CustomData::GetWellFaceStripData()
{
    return wellFaceStrip;
}

void CustomData::CalculateVertexDataAndFaceStripData(bool isString, bool isDependOther,ColorMap mapColor)
{
    float radian = qDegreesToRadians(0.0);
    if(isString)
    {
        stringVertorNum = lstStringX.count()* lstStringX.at(0).count();
        stringVertexData =VertexData();
        for(int i=0;i<lstStringX.count();i++)
        {
            for(int j=0;j<lstStringX.at(0).count();j++)
            {
                stringVertexData.position.append(calculateNormalizeData(isString,isDependOther,i,j));

                //calculate color;
                stringVertexData.color.append(calculateColorMap(isString,i,j,mapColor));

                //calculate normal
                stringVertexData.normal.append(calculateNormal(isString,i,j));

                //calculate texture;
                QVector2D tempV((float)(i+1)/lstStringX.count(),(float)(j+1)/lstStringX.at(0).count());
                QVector2D texture;
                texture.setX((tempV.x() - 0.5) * qCos(radian) - (tempV.y() - 0.5) * qSin(radian) + 0.5);
                texture.setY((tempV.x() - 0.5) * qSin(radian) - (tempV.y() - 0.5) * qCos(radian) + 0.5);

                stringVertexData.texCoord.append(texture);
                //stringVertexData.append(data);
            }
        }

        stringIndiceCount = 2 * (lstStringX.count()-1) * (lstStringX.at(0).count());
        stringFaceStrip = QVector<uint>();
        for(int i=0;i<lstStringZ.count()-1;i++)
        {
            for(int j=0; j<lstStringZ[0].count();j++)
            {
                uint nextCol = (j+1)%lstStringZ[0].count();
                if(j==0)
                {
                    stringFaceStrip.append(i * lstStringZ[0].count() + j);
                    stringFaceStrip.append(i * lstStringZ[0].count() + nextCol);
                }
                else
                {
                    stringFaceStrip.append((i+1) * lstStringZ[0].count() + j);
                    stringFaceStrip.append(i * lstStringZ[0].count() + nextCol);
                }

            }
        }

        stringFaceStrip.append(lstStringZ.count()-1 * lstStringZ[0].count()+1);
    }
    else
    {
        wellVertorNum = lstWellX.count()* lstWellX.at(0).count();
        wellVertexData = VertexData();
        for(int i=0;i<lstWellX.count();i++)
        {
            for(int j=0;j<lstWellX.at(0).count();j++)
            {

                wellVertexData.position.append(calculateNormalizeData(isString,isDependOther,i,j));

                wellVertexData.color.append(calculateColorMap(isString,i,j,mapColor));

                //calculate normal
                wellVertexData.normal.append(calculateNormal(isString,i,j));

                //calculate texture;
                QVector2D tempV((float)(i+1)/lstWellX.count(),(float)(j+1)/lstWellX.at(0).count());
                QVector2D texture;
                texture.setX((tempV.x() - 0.5) * qCos(radian) - (tempV.y() - 0.5) * qSin(radian) + 0.5);
                texture.setY((tempV.x() - 0.5) * qSin(radian) - (tempV.y() - 0.5) * qCos(radian) + 0.5);

                wellVertexData.texCoord.append(texture);
            }
        }


        wellIndiceCount = 2 * (lstWellX.count()-1) * (lstWellX.at(0).count());
        wellFaceStrip = QVector<uint>();
        for(int i=0;i<lstWellZ.count()-1;i++)
        {
            for(int j=0; j<lstWellZ[0].count();j++)
            {
                uint nextCol = (j+1)%lstWellZ[0].count();
                if(j==0)
                {
                    wellFaceStrip.append(i * lstWellZ[0].count() + j);
                    wellFaceStrip.append(i * lstWellZ[0].count() + nextCol);
                }
                else
                {
                    wellFaceStrip.append((i+1) * lstWellZ[0].count() + j);
                    wellFaceStrip.append(i * lstWellZ[0].count() + nextCol);
                }
            }
        }

        wellFaceStrip.append(lstWellZ.count()-1 * lstWellZ[0].count()+1);
    }
}

QVector3D CustomData::calculateNormalizeData(bool isString,bool isDependOther,int i,int j)
{

    if(isString)
    {
        if(i==0 && j==0)
        {
            if(isDependOther)
            {
                xMax = xSetMax;
                xMin = xSetMin;
                yMax = ySetMax;
                yMin = ySetMin;
                zMax = zSetMax;
                zMin = zSetMin;
            }
            else
            {
                xMax = xStringMax;
                xMin = xStringMin;
                yMax = yStringMax;
                yMin = yStringMin;
                zMax = zStringMax;
                zMin = zStringMin;
            }

            mStringMaxAxis = (yMax - yMin) > (xMax - xMin) ? 1 : 0;
            if(mStringMaxAxis == 1)
            {
                mStringMaxAxis = (zMax - zMin) > (yMax - yMin) ? 2:1;
            }
            else
            {
                mStringMaxAxis = (zMax - zMin) > (xMax - xMin) ? 2:0;
            }

            switch (mStringMaxAxis) {
            case 0:
            {
                xStringRate = 1;
                yStringRate = (yMax - yMin)/(xMax - xMin);
                zStringRate = (zMax - zMin)/(xMax - xMin);
            }
                break;
            case 1:
            {
                yStringRate = 1;
                xStringRate = (xMax - xMin)/(yMax - yMin);
                zStringRate = (zMax - zMin)/(yMax - yMin);
            }
                break;
            case 2:
            {
                zStringRate = 1;
                xStringRate = (xMax - xMin)/(zMax - zMin);
                yStringRate = (yMax - yMin)/(zMax - zMin);
            }
                break;
            default:
                break;
            }
        }

        float x = (lstStringX[i].at(j)-xMin)/(xMax - xMin)*2-1;
        x = x * xStringRate;
        float y = (lstStringY[i].at(j)-yMin)/(yMax - yMin)*2-1;
        y = y * yStringRate;
        float z = (lstStringZ[i].at(j)-zMin)/(zMax - zMin)*2-1;
        z = z * zStringRate;


        return QVector3D(x,y,z);
    }
    else
    {
        if(i==0 && j==0)
        {
            if(isDependOther)
            {
                xMax = xSetMax;
                xMin = xSetMin;
                yMax = ySetMax;
                yMin = ySetMin;
                zMax = zSetMax;
                zMin = zSetMin;
            }
            else
            {
                xMax = xWellMax;
                xMin = xWellMin;
                yMax = yWellMax;
                yMin = yWellMin;
                zMax = zWellMax;
                zMin = zWellMin;

            }

            mWellMaxAxis = (yMax - yMin) > (xMax - xMin) ? 1 : 0;
            if(mWellMaxAxis == 1)
            {
                mWellMaxAxis = (zMax - zMin) > (yMax - yMin) ? 2:1;
            }
            else
            {
                mWellMaxAxis = (zMax - zMin) > (xMax - xMin) ? 2:0;
            }

            switch (mWellMaxAxis) {
            case 0:
            {
                xWellRate = 1;
                yWellRate = (yMax - yMin)/(xMax - xMin);
                zWellRate = (zMax - zMin)/(xMax - xMin);
            }
                break;
            case 1:
            {
                yWellRate = 1;
                xWellRate = (xMax - xMin)/(yMax - yMin);
                zWellRate = (zMax - zMin)/(yMax - yMin);
            }
                break;
            case 2:
            {
                zWellRate = 1;
                xWellRate = (xMax - xMin)/(zMax - zMin);
                yWellRate = (yMax - yMin)/(zMax - zMin);
            }
                break;
            default:
                break;
            }

        }

        float x = (lstWellX[i].at(j)-xMin)/(xMax - xMin)*2-1;
        x = x * xWellRate;
        float y = (lstWellY[i].at(j)-yMin)/(yMax - yMin)*2-1;
        y = y * yWellRate;
        float z = (lstWellZ[i].at(j)-zMin)/(zMax - zMin)*2-1;
        z = z * zWellRate;

        return QVector3D(x,y,z);
    }
}

QVector3D CustomData::calculateNormal(bool isString,int i,int j)
{
    if(isString)
    {
        //calculate face normal
        if(i==0 && j==0)
        {
            lstStringFaceNormal.clear();
            for(int i=0; i< lstStringX.count()-1;i++)
            {
                QList<QVector3D> lstRowFaceNormal;
                for(int j=0;j<lstStringX[0].count()-1;j++)
                {
                    QVector3D vecA = QVector3D(lstStringX.at(i).at(j),lstStringY.at(i).at(j),lstStringZ.at(i).at(j));
                    QVector3D vecB = QVector3D(lstStringX.at(i).at(j+1),lstStringY.at(i).at(j+1),lstStringZ.at(i).at(j+1));
                    QVector3D vecC = QVector3D(lstStringX.at(i+1).at(j),lstStringY.at(i+1).at(j),lstStringZ.at(i+1).at(j));
                    QVector3D vecD = QVector3D(lstStringX.at(i+1).at(j+1),lstStringY.at(i+1).at(j+1),lstStringZ.at(i+1).at(j+1));

                    QVector3D vecAD = vecD - vecA;
                    QVector3D vecBC = vecB - vecC;

                    QVector3D faceNormal = QVector3D::crossProduct(vecAD,vecBC);
                    lstRowFaceNormal.append(faceNormal.normalized());
                }

                lstStringFaceNormal.append(lstRowFaceNormal);
            }
        }

        j = (j==lstStringX[0].count()-1) ? 0:j;
        int prontJ = (j-1) < 0? lstStringFaceNormal[0].count()-1:j-1;

        QVector3D verNormal;

        if(i==0)
        {

            QVector3D face1 = lstStringFaceNormal.at(i).at(j);
            QVector3D face2 = lstStringFaceNormal.at(i).at(prontJ);

            verNormal = (face1+face2) / 2;
        }
        else if(i==lstStringX.count()-1) {
            QVector3D face1 = lstStringFaceNormal.at(i-1).at(j);
            QVector3D face2 = lstStringFaceNormal.at(i-1).at(prontJ);

            verNormal = (face1+face2) / 2;
        }
        else
        {
            QVector3D face1 = lstStringFaceNormal.at(i-1).at(j);
            QVector3D face2 = lstStringFaceNormal.at(i-1).at(prontJ);
            QVector3D face3 = lstStringFaceNormal.at(i).at(j);
            QVector3D face4 = lstStringFaceNormal.at(i).at(prontJ);

            verNormal = (face1 + face2 + face3 + face4) / 4;
        }

        return verNormal.normalized();
    }
    else
    {
        if(i==0 && j==0)
        {
            lstWellFaceNormal.clear();
            for(int i=0; i< lstWellX.count()-1;i++)
            {
                QList<QVector3D> lstRowFaceNormal;
                for(int j=0;j<lstWellX[0].count()-1;j++)
                {
                    QVector3D vecA = QVector3D(lstWellX.at(i).at(j),lstWellY.at(i).at(j),lstWellZ.at(i).at(j));
                    QVector3D vecB = QVector3D(lstWellX.at(i).at(j+1),lstWellY.at(i).at(j+1),lstWellZ.at(i).at(j+1));
                    QVector3D vecC = QVector3D(lstWellX.at(i+1).at(j),lstWellY.at(i+1).at(j),lstWellZ.at(i+1).at(j));
                    QVector3D vecD = QVector3D(lstWellX.at(i+1).at(j+1),lstWellY.at(i+1).at(j+1),lstWellZ.at(i+1).at(j+1));

                    QVector3D vecAD = vecD - vecA;
                    QVector3D vecBC = vecB - vecC;

                    QVector3D faceNormal = QVector3D::crossProduct(vecAD,vecBC);
                    lstRowFaceNormal.append(faceNormal.normalized());
                }

                lstWellFaceNormal.append(lstRowFaceNormal);
            }
        }


        j = (j==lstWellX[0].count()-1) ? 0:j;
        int prontJ = (j-1) < 0? lstWellFaceNormal[0].count()-1:j-1;

        QVector3D verNormal;

        if(i==0)
        {

            QVector3D face1 = lstWellFaceNormal.at(i).at(j);
            QVector3D face2 = lstWellFaceNormal.at(i).at(prontJ);

            verNormal = (face1+face2) / 2;
        }
        else if(i==lstWellX.count()-1) {
            QVector3D face1 = lstWellFaceNormal.at(i-1).at(j);
            QVector3D face2 = lstWellFaceNormal.at(i-1).at(prontJ);

            verNormal = (face1+face2) / 2;
        }
        else
        {
            QVector3D face1 = lstWellFaceNormal.at(i-1).at(j);
            QVector3D face2 = lstWellFaceNormal.at(i-1).at(prontJ);
            QVector3D face3 = lstWellFaceNormal.at(i).at(j);
            QVector3D face4 = lstWellFaceNormal.at(i).at(prontJ);

            verNormal = (face1 + face2 + face3 + face4) / 4;
        }

        return verNormal.normalized();
    }
}

QVector3D CustomData::calculateColorMap(bool isString,int i,int j,ColorMap colorMap)
{

    float stepZ =0;
    if(isString)
    {
        stepZ =(zStringMax - zStringMin)/colorMap.mapLevels;
    }
    else
    {
        stepZ =(zWellMax - zWellMin)/colorMap.mapLevels;
    }

    float redStart = colorMap.minColor.redF();
    float blueStart = colorMap.minColor.blueF();
    float greenStart = colorMap.minColor.greenF();

    float redStop = colorMap.maxColor.redF();
    //redStop = redStop <= redStart ? redStop + 1.0 : redStop;
    float blueStop = colorMap.maxColor.blueF();
    //blueStop = blueStop <= blueStart ? blueStop + 1.0 : blueStop;
    float greenStop = colorMap.maxColor.greenF();
    //greenStop = greenStop <= greenStart ? greenStop + 1.0 : greenStop;

    float redStep = (redStop - redStart) / colorMap.mapLevels;
    float greenStep = (greenStop - greenStart) / colorMap.mapLevels;
    float blueStep = (blueStop - blueStart) / colorMap.mapLevels;

    QVector3D vectorColor;
    //qDebug()<<colorMap.mapLevels<<","<<colorMap.maxColor <<","<<colorMap.minColor;

    for(uint k=0;k<colorMap.mapLevels;k++)
    {
        if(isString)
        {
            if(lstStringZ.at(i).at(j) >= (zStringMin + stepZ * k) && lstStringZ.at(i).at(j) < (zStringMin + stepZ * ( k + 1)))
            {
                float redCur = redStart + k * redStep;
                //redCur = redCur > 1.0 ? redCur - 1.0 : redCur;
                float greenCur = greenStart + k * greenStep;
                //greenCur = greenCur > 1.0 ? greenCur - 1.0 : greenCur;
                float blueCur = greenStart + k * blueStep;
                //blueCur = blueCur > 1.0 ? blueCur - 1.0 : blueCur;
                vectorColor= QVector3D(redCur,greenCur,blueCur);
                //qDebug()<<vectorColor.x()<<vectorColor.y()<<vectorColor.z();
                break;
            }

            if(lstStringZ.at(i).at(j) >=(zStringMin + stepZ * colorMap.mapLevels))
            {
                vectorColor = QVector3D(redStop,greenStop,blueStop);
                break;
            }
        }
        else
        {
            if(lstWellZ.at(i).at(j) >= (zWellMin + stepZ * k) && lstWellZ.at(i).at(j) < (zWellMin + stepZ * ( k + 1)))
            {
                float redCur = redStart + k * redStep;
                //redCur = redCur > 1.0 ? redCur - 1.0 : redCur;
                float greenCur = greenStart + k * greenStep;
                //greenCur = greenCur > 1.0 ? greenCur - 1.0 : greenCur;
                float blueCur = greenStart + k * blueStep;
                //blueCur = blueCur > 1.0 ? blueCur - 1.0 : blueCur;
                vectorColor= QVector3D(redCur,greenCur,blueCur);
                //qDebug()<<vectorColor.x()<<vectorColor.y()<<vectorColor.z();
                break;
            }

            if(lstWellZ.at(i).at(j) >=(zWellMin + stepZ * colorMap.mapLevels))
            {
                vectorColor = QVector3D(redStop,greenStop,blueStop);
                break;
            }
        }
    }

    return vectorColor;
}
